package com.quectel.taskserver.job.scheduling;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.quectel.business.common.scheduling.SchedulingLeaveBusiness;
import com.quectel.constant.core.scheduling.SchedulingApplyConstants;
import com.quectel.constant.core.scheduling.SchedulingLeaveConstants;
import com.quectel.core.module.dept.service.DeptPersonService;
import com.quectel.core.module.scheduling.service.SchedulingLeaveBalanceService;
import com.quectel.core.module.scheduling.service.SchedulingLeaveConfigService;
import com.quectel.core.module.scheduling.service.SchedulingLeavePersonBindingService;
import com.quectel.core.module.schedulingapply.dto.SchedulingApplyLeaveRecordDto;
import com.quectel.core.module.schedulingapply.dto.vo.SchedulingBalanceTimeVO;
import com.quectel.core.module.schedulingapply.service.SchedulingApplyLeaveRecordService;
import com.quectel.util.common.DateUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.shardingsphere.elasticjob.api.ShardingContext;
import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangheng
 * @date 2023/08/01 7:24 下午
 */
@Component
public class SchedulingLeaveBalanceRecycleTask implements SimpleJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(SchedulingLeaveBalanceRecycleTask.class);

    @DubboReference
    private DeptPersonService deptPersonService;
    @DubboReference
    private SchedulingLeaveConfigService schedulingLeaveConfigService;
    @DubboReference
    private SchedulingLeavePersonBindingService schedulingLeavePersonBindingService;
    @DubboReference
    private SchedulingLeaveBalanceService schedulingLeaveBalanceService;
    @Autowired
    private SchedulingLeaveBusiness schedulingLeaveBusiness;
    @Autowired
    private SchedulingApplyLeaveRecordService schedulingApplyLeaveRecordService;


    @Override
    public void execute(ShardingContext shardingContext) {
        recycle();
    }


    /**
     * 回收结束时间大于当前时间并且 calCursorTime不等于endTime的假期余额
     */
    private void recycle() {
        Date now = new Date();
        DateTime recycleDate = DateUtil.offsetDay(now, -1);
        Map<String, Object> params = new HashMap<>();
        params.put(SchedulingLeaveConstants.RECYCLE_DATE, DateUtils.format(recycleDate, DateUtils.FormatType.COMMON));
        List<SchedulingApplyLeaveRecordDto> schedulingApplyLeaveRecordDtos = schedulingApplyLeaveRecordService.queryList(params);
        if (CollectionUtils.isEmpty(schedulingApplyLeaveRecordDtos)) {
            for (SchedulingApplyLeaveRecordDto dto : schedulingApplyLeaveRecordDtos) {
                //计算两个时间的差值
                if (dto.getCalCursorTime().after(dto.getEndTime())) {
                    continue;
                }
                long mills = dto.getEndTime().getTime() - dto.getCalCursorTime().getTime();

                SchedulingLeaveConstants.TimeUnitEnum byUnit = SchedulingLeaveConstants.TimeUnitEnum.getByUnit(dto.getTimeUnit());
                if (byUnit == null) {
                    continue;
                }
                if (dto.getBalanceDetail() == null || CollectionUtils.isEmpty(dto.getBalanceDetail().getBalanceTimes())) {
                    continue;
                }
                //需要回收的余额
                BigDecimal balance = BigDecimal.valueOf(mills).divide(BigDecimal.valueOf(byUnit.getMillis()), SchedulingLeaveConstants.DEFAULT_SCALE, RoundingMode.HALF_UP);

                //换算单位
                List<SchedulingBalanceTimeVO> balanceTimes = dto.getBalanceDetail().getBalanceTimes();
                for (SchedulingBalanceTimeVO balanceTime : balanceTimes) {
                    //如果回收的余额小于申请余额 则一次性回收
                    if (balanceTime.getAppliedBalance().compareTo(balance) > 0) {
                        BigDecimal appliedBalanceMills = balanceTime.getAppliedBalance();
                        balanceTime.setAppliedBalance(appliedBalanceMills.subtract(balance));
                        //回收余额
                        schedulingLeaveBalanceService.updateBalance(
                                dto.getApplyDeptPersonId(),
                                SchedulingApplyConstants.BalanceTypeEnum.DAILY_CAL_UPDATE.getType(),
                                dto.getApplyRecordId(),
                                balanceTime.getBalanceId(),
                                appliedBalanceMills,
                                dto.getTimeUnit()
                        );
                    } else {
                        balance = balance.subtract(balanceTime.getAppliedBalance());
                        balanceTime.setAppliedBalance(BigDecimal.ZERO);
                        //回收余额
                        schedulingLeaveBalanceService.updateBalance(
                                dto.getApplyDeptPersonId(),
                                SchedulingApplyConstants.BalanceTypeEnum.DAILY_CAL_UPDATE.getType(),
                                dto.getApplyRecordId(),
                                balanceTime.getBalanceId(),
                                balanceTime.getAppliedBalance(),
                                dto.getTimeUnit());
                    }
                }

                //更新对应的时间
                dto.setTimeLength(dto.getTimeLength().multiply(balance));
                dto.setCalCursorTime(dto.getEndTime());
                schedulingApplyLeaveRecordService.updateById(dto);
            }
        }

    }

}
